/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1/commercial
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may use this file in compliance with the License.
 * Alternatively, if you can't copy with the License, namely if you do not
 * want to provide source code of your modifications to this file, you may
 * negotiate a commercial licence with the initial developer.
 * You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is COID.
 *
 * The Initial Developer of the Original Code is
 * PosAm.
 * Portions created by the Initial Developer are Copyright (C) 2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 * Brano Kemen
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#ifndef __COID_SERVER_THREADMGR__HEADER_FILE__
#define __COID_SERVER_THREADMGR__HEADER_FILE__

#include "coid/comm/str.h"
#include "coid/comm/local.h"
#include "coid/comm/radix.h"
#include "coid/comm/sync/thread_mgr.h"


COID_NAMESPACE_BEGIN


////////////////////////////////////////////////////////////////////////////////
struct thread_info
{
    uint            _oid;               ///< owner object id
    uint            _flags;

    void*           _arg;
    t_thread_fnc    _fnc;
    
    charstr         _name;              ///< thread name
    uint            _tempid;            ///< temporary object id

    enum {
        fCRITICAL                       = 1,    ///< thread is critical, after exit, add the owner id to dead
    };

    thread_info()
    {
        _oid = _tempid = UMAX32;
        _flags = 0;
        _arg = 0;
        _fnc = 0;
    }
};


////////////////////////////////////////////////////////////////////////////////
class ThreadMgr
{
public:

#   define def_get_thread_var(T,var) \
    static void extract_thread_var_##var( void* val, void* ctx ) { *(T*)val = ((thread_info*)ctx)->_##var; } \
    static void modify_thread_var_##var( void* val, void* ctx )  { ((thread_info*)ctx)->_##var = *(const T*)val; } \
    static opcd get_thread_##var( thread_t tid, T& val ) \
    { return SINGLETON(thread_manager).access_context_value( tid, &val, &extract_thread_var_##var ); } \
    static opcd set_thread_##var( thread_t tid, const T& val ) \
    { return SINGLETON(thread_manager).access_context_value( tid, (T*)&val, &modify_thread_var_##var ); }


    def_get_thread_var(charstr,name);
    def_get_thread_var(uint,oid);
    def_get_thread_var(uint,tempid);


    static void extract_thread_info( void* val, void* ctx )  { *(thread_info*)val = *((thread_info*)ctx); }

    static opcd get_thread_info( thread_t tid, thread_info& val )
    { return SINGLETON(thread_manager).access_context_value( tid, &val, &extract_thread_info ); }

/*
    thread_info* thread_initialize( void* handle, void* arg, t_thread_fnc f, bool crit, uint oid, charstr& name, uint tempid=UMAX )
    {
        thread_info* ti = new thread_info;
        ti->_arg = arg;
        ti->_fnc = f;
        ti->_oid = oid;
        ti->_name.takeover(name);
        ti->_tempid = tempid == UMAX  ?  oid  :  tempid;
        ti->_flags = crit ? thread_info::fCRITICAL : 0;
        
        ti->_threaduid = thread::self();
        ti->_handle = handle;

        _pkey.set(ti);

        GUARDME;
        _hash.insert_value( std::pair<uint,thread_info*>((uint)thread::self(), ti) );
        return ti;
    }

    thread_info* thread_initialize( thread_info* ti )
    {
        _pkey.set(ti);

        GUARDME;
        _hash.insert_value( std::pair<uint,thread_info*>((uint)thread::self(), ti) );
        return ti;
    }

    void thread_delete( uint tid )
    {
        GUARDME;

        thread_info** pti = _hash.find_value(tid);
        if(pti)
        {
            delete *pti;
            _hash.erase(tid);
        }
    }
*/
private:
};


COID_NAMESPACE_END


#endif //__COID_SERVER_THREADMGR__HEADER_FILE__
